﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace XHFrame
{
    public class SceneManager : Singleton<SceneManager>
    {
        public class SceneInfoData
        {
            public string SceneName { get; private set; }
            public object[] Params { get; private set; }
            public Type SceneType { get; private set; }

            public SceneInfoData(string SceneName, Type SceneType, params object[] Params)
            {
                this.SceneType = SceneType;
                this.SceneName = SceneName;
                this.Params = Params;
            }
        }

        Debuger log = Debuger.GetLogger(typeof(SceneManager));

        private Dictionary<EnumSceneType, SceneInfoData> dicSceneInfos = null;

        /// <summary>
        /// 正在的场景
        /// </summary>
        public EnumSceneType LastSceneType { get; set; }

        /// <summary>
        /// 需要切换的场景
        /// </summary>
        public EnumSceneType ChangeSceneType { get; private set; }

        private BaseScene currentScene;
        public BaseScene CurrentScene
        {
            get
            {
                return currentScene;
            }

            set
            {
                currentScene = value;
            }
        }

        private EnumUIType SceneOpenUIType = EnumUIType.None;
        private object[] SceneOpenUIParams = null;

        public void RegisterAllScene()
        {
            // 注册格式
            //RegisterScene(EnumSceneType.StartGame,"StartGameScene",typeof(XXXX),null);
            //RegisterScene(EnumSceneType.MainScene, "MainScene", null, null);
            //RegisterScene(EnumSceneType.LoegScene, "LoegScene", null, null);
            //RegisterScene(EnumSceneType.CopyScene, "CopyScene", null, null);
        }


        public override void Init()
        {
            base.Init();
            dicSceneInfos = new Dictionary<EnumSceneType, SceneInfoData>();
        }
        /// <summary>
        /// 注册场景
        /// </summary>
        /// <param name="_SceneID">场景ID</param>
        /// <param name="_sceneName">场景名</param>
        /// <param name="_sceneType">场景类型</param>
        /// <param name="_params">可扩展参数</param>
        public void RegisterScene(EnumSceneType _SceneID, string _sceneName, Type _sceneType, params object[] _params)
        {
            if (_sceneType == null || _sceneType != typeof(BaseScene))
            {
                throw new Exception("Register scene type must not null nd extends BaseScene");
            }

            if (dicSceneInfos.ContainsKey(_SceneID))
            {
                SceneInfoData info = new SceneInfoData(_sceneName, _sceneType, _params);
                dicSceneInfos.Add(_SceneID, info);
            }
        }

        /// <summary>
        /// 删除注册的场景
        /// </summary>
        /// <param name="_sceneID">场景ID</param>
        public void UnRegisterScene(EnumSceneType _sceneID)
        {
            if (dicSceneInfos.ContainsKey(_sceneID))
            {
                dicSceneInfos.Remove(_sceneID);
            }
        }

        /// <summary>
        /// 是否已注册
        /// </summary>
        /// <param name="_sceneID">场景ID</param>
        /// <returns></returns>
        public bool IsRegisterScene(EnumSceneType _sceneID)
        {
            return dicSceneInfos.ContainsKey(_sceneID);
        }

        /// <summary>
        /// 返回场景信息
        /// </summary>
        /// <param name="sceneID">场景ID</param>
        /// <returns></returns>
        public SceneInfoData GetSceneInfo(EnumSceneType sceneID)
        {
            if (dicSceneInfos.ContainsKey(sceneID))
            {
                return dicSceneInfos[sceneID];
            }
            log.E("This Scene Is Not Register! id:" + sceneID.ToString());
            Debug.LogError("This Scene Is Not Register! id:" + sceneID.ToString());
            return null;
        }

        /// <summary>
        /// 注销场景
        /// </summary>
        public void ClearScene()
        {
            dicSceneInfos.Clear();
        }

        /// <summary>
        /// 返回场景名
        /// </summary>
        /// <param name="sceneID">需要返回的场景ID</param>
        /// <returns></returns>
        public string GetSceneName(EnumSceneType sceneID)
        {
            if (dicSceneInfos.ContainsKey(sceneID))
            {
                return dicSceneInfos[sceneID].SceneName;
            }
            log.E("This Scene Is Not Register! id:" + sceneID.ToString());
            Debug.LogError("This Scene Is Not Register! id:" + sceneID.ToString());
            return null;
        }

        #region Change Scene 改变场景

        #region 直接切换场景
        /// <summary>
        /// 直接切换场景
        /// </summary>
        /// <param name="sceneType">场景类型</param>
        /// <param name="uiType">UI类型</param>
        /// <param name="_params">可变参数</param>
        public void ChangeSceneDirect(EnumSceneType sceneType, EnumUIType uiType, params object[] _params)
        {
            SceneOpenUIParams = _params;
            SceneOpenUIType = uiType;
            if (LastSceneType == sceneType)
            {
                if (SceneOpenUIType == EnumUIType.None)
                {
                    return;
                }
                UIManager.Instance.OpenUI(SceneOpenUIType, SceneOpenUIParams);
                SceneOpenUIType = EnumUIType.None;
            }
            else
            {
                ChangeSceneDirect(LastSceneType);
            }
        }
        /// <summary>
        /// 直接切换场景
        /// </summary>
        /// <param name="sceneType">场景类型</param>
        public void ChangeSceneDirect(EnumSceneType sceneType)
        {
            UIManager.Instance.CloseUIAll();

            if (CurrentScene != null)
            {
                CurrentScene.Release();
                CurrentScene = null;
            }

            LastSceneType = ChangeSceneType;
            ChangeSceneType = sceneType;

            string sceneName = GetSceneName(sceneType);
            // change scene

            CoroutineController.Instance.StartCoroutine(AsyncLoadScene(sceneName));

        }

        /// <summary>
        /// 异步切换场景
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private IEnumerator<AsyncOperation> AsyncLoadScene(string fileName)
        {
            AsyncOperation oper = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(fileName);

            yield return oper;

            // Message Send
            if (SceneOpenUIType != EnumUIType.None)
            {
                UIManager.Instance.OpenUI(SceneOpenUIType, SceneOpenUIParams);
                SceneOpenUIType = EnumUIType.None;
            }

        }
        #endregion

        #region 通过Loading切换场景
        /// <summary>
        /// 直接切换场景
        /// </summary>
        /// <param name="sceneType">场景类型</param>
        /// <param name="uiType">UI类型</param>
        /// <param name="_params">可变参数</param>
        public void ChangeScene(EnumSceneType sceneType, EnumUIType uiType, params object[] _params)
        {
            SceneOpenUIParams = _params;
            SceneOpenUIType = uiType;
            if (LastSceneType == sceneType)
            {
                if (SceneOpenUIType == EnumUIType.None)
                {
                    return;
                }
                UIManager.Instance.OpenUI(SceneOpenUIType, SceneOpenUIParams);
                SceneOpenUIType = EnumUIType.None;
            }
            else
            {
                ChangeScene(LastSceneType);
            }
        }
        /// <summary>
        /// 直接切换场景
        /// </summary>
        /// <param name="sceneType">场景类型</param>
        public void ChangeScene(EnumSceneType sceneType)
        {
            UIManager.Instance.CloseUIAll();

            if (CurrentScene != null)
            {
                CurrentScene.Release();
                CurrentScene = null;
            }

            LastSceneType = ChangeSceneType;
            ChangeSceneType = sceneType;

            string sceneName = GetSceneName(sceneType);
            // change loading scene

            CoroutineController.Instance.StartCoroutine(AsyncLoadOtherScene());

        }

        /// <summary>
        /// 异步切换场景
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private IEnumerator AsyncLoadOtherScene()
        {
            string sceneName = GetSceneName(EnumSceneType.LoadingScene);

            var oper = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(sceneName);

            yield return null;

            // Message Send
            if (oper.isDone)
            {
                //GameObject go = GameObject.Find("LoadingScenePanel");
                //LoadingSceneUI loadingSceneUI = go.GetComponent<LoadingSceneUI>();
                //BaseScene scene = CurrentScene;
                //if (null != scene)
                //    scene.CurrentSceneId = ChangeSceneId;
                //// 检测是否注册该场景
                //if (!SceneManager.Instance.IsRegisterScene(ChangeSceneId))
                //    Debug.LogError("没有注册此场景!"+ ChangeSceneId.ToString());
                //LoadingSceneUI.Load(ChangeSceneId);
                //LoadingSceneUI.LoadCompleted += SceneLoadCompleted;
            }

            if (SceneOpenUIType != EnumUIType.None)
            {
                UIManager.Instance.OpenUI(SceneOpenUIType, SceneOpenUIParams);
                SceneOpenUIType = EnumUIType.None;
            }

        }

        void SceneLoadCompleted(object scener, EventArgs e)
        {
            Debug.Log("切换场景完成!"+scener as String);
            // 场景切换完成
            // MessageCeneter.Instance.SendMessage(MessageType.GAMESCENE_CHANGECOMPLETE,this,null,false)

            // 有要打开的UI
            if (SceneOpenUIType != EnumUIType.None)
            {
                UIManager.Instance.OpenUI(SceneOpenUIType, SceneOpenUIParams);
                SceneOpenUIType = EnumUIType.None;
            }

        }

        //		//加载场景
        //		private IEnumerator AsyncLoadedNextScene()
        //		{
        //			string fileName = SceneManager.Instance.GetSceneName(ChangeSceneId);
        //			AsyncOperation oper = Application.LoadLevelAsync(fileName);
        //			yield return oper;
        //			if (oper.isDone)
        //			{
        //				if (LoadCompleted != null)
        //					LoadCompleted(changeSceneId, null);
        //			}
        //		}

        //		BaseScene scene = Game.Instance.GetBaseScene(Game.Instance.ChangeSceneId);
        //		CurrentScene = scene;
        //		scene.Load();
        #endregion
        #endregion
    }
}
